// import fs = require("fs")
// import path = require("path")
// import { SocketConnectionManager } from "./SocketConnectionManager";
// import { SocketClient } from "./SocketClient";
// import { ProtoUtils } from "../protocol/ProtoUtils";
// import { ProtoConfig } from "../protocol/ProtoConfig";
// import { Buffer } from "buffer";
// import { RetCodeDefine } from "../protocol/RetCodeDefine"

import { Logger } from "../../utils/Logger";
import { ProtoConfig } from "../protocol/ProtoConfig";
import { ProtoUtils } from "../protocol/ProtoUtils";
import { SocketMsg } from "./SocketMsg";
import { SocketConnectionManager } from "./SocketConnectionManager";
import { UserModel } from "../../../model/UserModel";
import { SocketClientMsgHandler } from "./SocketClientMsgHandler";

export class SocketConnection {

    public static ReadyState = {
        Open: 1,
        Close: 3
    }

    private static id: number = 0;

    public id: number = 0;
    private connection: any;
    private isDestroyed: boolean = false;
    public user: UserModel;
    public ip: string;
    private interval;
    private timeId;
    public isClosing: boolean;


    constructor(connection, ip: string) {
        this.connection = connection;
        SocketConnection.id++;
        this.ip = ip
        this.id = SocketConnection.id;
        this.initConnect();
    }

    private initConnect() {
        this.isDestroyed = false;
        this.isClosing = false;
        this.connection.on('message', (data) => {
            this.onClientMsgHandler(data)
        });
        this.interval = setInterval(() => {
            this.checkConnection();
        }, 1000);
    }

    private checkConnection() {
        if (this.connection.readyState == SocketConnection.ReadyState.Close) {
            this.connection.terminate();
            this.destroy();
            return false;
        }
        return true;
    }


    public gotoClose() {
        this.isClosing = true;
        this.timeId = setTimeout(() => {
            this.close(true)
        }, 1000)
    }

    private close(isForce: boolean = false) {
        if (this.connection.readyState == SocketConnection.ReadyState.Open || isForce) {
            this.connection.terminate();
            this.destroy();
        }
    }

    private onClientMsgHandler(data) {
        try {
            let byteArray: Uint8Array = new Uint8Array(data);
            let totalPack = ProtoUtils.DeserializeBinary(ProtoConfig.PB_MESSAGE, byteArray);
            // Logger.log("onClientMsgHandler========", totalPack);
            let reqId: number = totalPack.getSeq();
            let protoType: number = totalPack.getHead();
            let protoData = totalPack.getData();
            let protoName: string = ProtoConfig.getProtoReqName(protoType);
            let msg: SocketMsg = SocketMsg.createSocketMsg(reqId, protoType, protoName, protoData);
            SocketClientMsgHandler.onEventSocketGata(this, msg);
        } catch (error) {
            Logger.error("onClientMsgHandler======error==", error);
        }
    }

    private createSendPack(socketMsg: SocketMsg): Uint8Array {
        let serialdata: Uint8Array = socketMsg.protoData.serializeBinary();
        let totalPack = ProtoUtils.Create(ProtoConfig.PB_MESSAGE);
        totalPack.setSeq(socketMsg.reqId);
        totalPack.setHead(socketMsg.protoType);
        totalPack.setData(serialdata);
        return totalPack.serializeBinary();
    }

    public createMsgToClient(reqId: number, protoName: string, respPack: any) {
        let protoType: number = ProtoConfig.getProtoResponeseType(protoName);
        let socketMsg: SocketMsg = SocketMsg.createSocketMsg(reqId, protoType, protoName, respPack);
        this.sendMsgToClient(socketMsg);
    }

    public sendMsgToClient(socketMstg: SocketMsg) {
        if (!this.checkConnection()) {
            return;
        }
        if (!this.isDestroyed) {
            let totalPack: Uint8Array = this.createSendPack(socketMstg);
            let sendBuff: Buffer = Buffer.from(totalPack);
            this.connection.send(sendBuff);
        } else {
            Logger.error("sendMsgToClient=error=", this.id, socketMstg);
        }
    }


    public isLogin(): boolean {
        if (this.user) {
            return true;
        } else {
            return false;
        }
    }

    private destroy() {
        if (!this.isDestroyed) {
            clearTimeout(this.timeId)
            clearInterval(this.interval)
            this.isDestroyed = true;
            SocketConnectionManager.instance.removeSocketConnection(this);
            Logger.log("socket connnect destroy==", SocketConnectionManager.instance.socketConnList.length);
        }
    }
}